/*
 * Created: 2022-07-07 21:59:54
 * Author : 涛涛涛
 */

import Taro from '@tarojs/taro';
import { myEnv } from '@/myEnv';
/**
 * 作者: 涛涛涛
 * 创建时间: 2021-12-14 14:56:25
 * 发送请求对象,简单的发送一个请求,类似于axios原生的使用方式,只设置了基础访问路径
 */
export type RequestParams = {
    /** 请求地址 */
    url: string;
    /** 请求数据 */
    data?: any;
    /** 请求头 */
    header?: { [propName: string]: string };
    /** 请求方式 */
    method?: 'GET' | 'POST' | 'PUT';
    /** 响应超时【ms】 */
    timeout?: number;
};
/** 发送请求
 * 简单的发送一个请求,类似于axios原生的使用方式,只设置了基础访问路径
 */

export const requestSimpleness = async <T>(params: RequestParams) => {
    let { url, method = 'POST', timeout = 60 * 1000, header, ...other } = params;
    let token = null;
    try {
        var value = Taro.getStorageSync('token');
        token = value;
    } catch (e) {
        console.log(e);
    }

    if (token) {
        const _header = { ...header, token };
        header = _header;
    }

    if (!/^https?.*/.test(url)) {
        if (url.substring(0, 1) === '/') {
            url = `${myEnv.BASE_URL}${url}`;
        } else {
            url = `${myEnv.BASE_URL}/${url}`;
        }
    }
    let response = await new Promise((resolve, reject) => {
        Taro.request({
            ...other,
            url,
            method,
            timeout,
            header,
            success: (successInfo) => {
                const businessData = interceptNumberSwitchString(successInfo.data);
                if (businessData.code === '401') {
                    Taro.redirectTo({
                        url: 'pages/Login/Login',
                    });
                    Taro.removeStorageSync('token');
                    setTimeout(() => {
                        Taro.showToast({
                            title: '请重新登录',
                            icon: 'none',
                        });
                    }, 500);
                } else if (businessData.code !== '200') {
                    console.error('业务接口异常,code!==200', successInfo);
                    Taro.showToast({
                        title: successInfo.data.message,
                        icon: 'none',
                    });
                    resolve(null);
                    return;
                }
                resolve(businessData);
            },
            fail: (errorResponse: any) => {
                console.error('网络请求异常!', errorResponse);
                resolve(null);
            },
        });
    });
    return response as Promise<T>;
};

type Resolve = (value: unknown) => void;
const requestTaskMapper: { [key: string]: Resolve[] } = {};
/** 为请求扩展合并请求的功能 */
export const mergeRequest = async <T>(requestParams: RequestParams) => {
    const mapperKey = JSON.stringify(requestParams);
    if (!requestTaskMapper[mapperKey]) requestTaskMapper[mapperKey] = [];
    const currentTaskQueue = requestTaskMapper[mapperKey];
    let promise: Promise<MyResponse<T>> = new Promise((resolve) => {
        currentTaskQueue.push(resolve);
    });
    /** 如果已经在发送请求了,则直接返回promise等待一起接收结果 */
    if (currentTaskQueue.length > 1) return promise;
    /** 如果还没有开始发送请求,则发送请求 */
    let result = await requestSimpleness(requestParams);
    currentTaskQueue.forEach((resolve) => {
        /** 如果同一份数据有多个接收对象,需要深拷贝,去掉指向 */
        if (requestTaskMapper[mapperKey].length === 1) resolve(result);
        else resolve(JSON.parse(JSON.stringify(result)));
    });
    delete requestTaskMapper[mapperKey];
    return promise;
};

/** 将所有数字转成字符串 */
const interceptNumberSwitchString = (data) => {
    if (typeof data === 'number') {
        return String(data);
    }
    if (Object.prototype.toString.call(data) === '[object Object]') {
        const localData = { ...data };
        for (const key in localData) {
            localData[key] = interceptNumberSwitchString(localData[key]);
        }
        return localData;
    }
    if (Object.prototype.toString.call(data) === '[object Array]') {
        const localData = [...data];
        for (var i = 0; i < localData.length; i++) {
            localData[i] = interceptNumberSwitchString(localData[i]);
        }
        return localData;
    }
    return data;
};
